package cn.edu.gdut.deepcode.aspect;

import cn.edu.gdut.deepcode.context.UserContext;
import cn.edu.gdut.deepcode.domain.dto.CanvasDTO;
import cn.edu.gdut.deepcode.domain.dto.CanvasOperationDTO;
import cn.edu.gdut.deepcode.domain.po.Canvas;
import cn.edu.gdut.deepcode.domain.po.Result;
import cn.edu.gdut.deepcode.service.ICanvasService;
import cn.edu.gdut.deepcode.utils.CommonUtils;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

import static cn.edu.gdut.deepcode.constant.AbnormalInfoConstant.*;
import static cn.edu.gdut.deepcode.constant.CacheConstant.CANVAS_SHARED_CODE_PREFIX;
import static cn.edu.gdut.deepcode.constant.ReqRespConstant.REPEAT_GEN_SHARED_CODE_CODE;
import static cn.edu.gdut.deepcode.constant.ReqRespConstant.REPEAT_GEN_SHARED_CODE_MSG;

/**
 * <p>
 * 画布切面,用于校验画布id合法性
 * </p>
 *
 * @Author: 暮倦
 * @Since: 2025-04-12  11:19
 * @Version: 1.0.0
 */
@Slf4j
@RequiredArgsConstructor
@Aspect
@Component
public class CanvasAspect {
    private final ICanvasService canvasService;


    private final StringRedisTemplate redisTemplate;

    private final ExecutorService checkCanvasIdValidatedExecutorService;

    @Pointcut("@annotation(cn.edu.gdut.deepcode.annotation.CanvasIdCheckPoint)")
    public void canvasIdCheckPoint() {
    }

    @Pointcut("@annotation(cn.edu.gdut.deepcode.annotation.GenSharedCodeCheckPoint)")
    public void genSharedCodeCheckPoint() {
    }

    @Around("canvasIdCheckPoint()")
    public Object aCheckCanvasIdValidated(ProceedingJoinPoint joinPoint) throws Throwable {
        // 利用CompletableFuture检查此次操作是否为异常操作
        Object[] args = joinPoint.getArgs();
        Long userId = UserContext.getUser();
        CompletableFuture.runAsync(
                () -> {
//                    long start=System.currentTimeMillis();
                    Long canvasId;
                    Object arg = args[0];
                    if (arg instanceof CanvasDTO canvasDTO) {
                        // 第一参数为dto对象
                        canvasId = canvasDTO.getCanvasId();
                    } else if (arg instanceof CanvasOperationDTO canvasOperationDTO) {
                        canvasId = canvasOperationDTO.getCanvasId();
                    } else {
                        // 第一参数为画布id
                        canvasId = (Long) arg;
                    }
                    if (canvasId != null) {
                        // 根据画布id,用户id查看画布是否存在
                        Long count = canvasService
                                .lambdaQuery()
                                .eq(Canvas::getUserId, userId)
                                .eq(Canvas::getCanvasId, canvasId)
                                .count();
                        if (count != 1) {
                            // 不存在则记录信息
//                            log.error(CI_EI_1,
//                                    List.of(userId, canvasId,args,count));
                        }
                    } else {
                        // 不存在则记录信息
                        log.error(CI_EI_1,
                                List.of(userId, canvasId,args));
                    }
//                    log.info("执行时间 -> {}",System.currentTimeMillis()-start);
                },checkCanvasIdValidatedExecutorService);

        return joinPoint.proceed(args);
    }

    @Around("genSharedCodeCheckPoint()")
    public Object bCheckGenSharedCodeValidated(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取画布id
        Object[] args = joinPoint.getArgs();
        Long canvasId = (Long) args[0];
        // 查看当前用户是否为画布主人
        Long userId = UserContext.getUser();
        Long count = canvasService.lambdaQuery()
                .eq(Canvas::getCanvasId, canvasId)
                .eq(Canvas::getUserId, userId)
                .eq(Canvas::getOwnerId, userId)
                .count();
        if (count != 1) {
            // 不是主人
            CommonUtils.recordErrorInfoAndThrowException(
                    CS_EI_2,
                    List.of(userId, canvasId, count)
            );
        }
        // 根据画布id获得分享码,查看分享码是否过期
        String sharedCode = redisTemplate.opsForValue().get(CANVAS_SHARED_CODE_PREFIX + canvasId);
        if (StrUtil.isNotBlank(sharedCode)) {
            // 缓存不为空说明分享码已存在
            log.warn(
                    CS_EI_1,
                    List.of(userId, canvasId, sharedCode)
            );
            // 重复生成分享码,返回空数据
            return Result.error(
                    REPEAT_GEN_SHARED_CODE_CODE,
                    REPEAT_GEN_SHARED_CODE_MSG
            );
        }
        // 检查通过,返回方法执行结果
        return joinPoint.proceed(args);
    }

}


